package com.jiangyg.mall.core;

import com.jiangyg.mall.core.constant.CoreConstant;
import com.jiangyg.mall.core.support.env.EnvConstant;
import com.jiangyg.mall.core.support.async.AsyncUncaughtExceptionHandlerImpl;
import com.jiangyg.mall.core.utils.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * 类描述：配置一个线程池
 *
 * @author jiangyg
 * @version 4.0
 * @date 2021-12-14
 */
@Slf4j
@EnableAsync
@Configuration
@ConditionalOnProperty(name = "spring.async.enabled", havingValue = "true")
public class AsyncAutoConfiguration implements AsyncConfigurer, InitializingBean {

    @Override
    @Bean(CoreConstant.ASYNC_EXECUTOR)
    public TaskExecutor getAsyncExecutor() {
        final ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 服务器CPU核心数
        int corePoolSize = EnvConstant.getInt("spring.async.corePoolSize");
        if (corePoolSize == -1) {
            corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
        }
        // 根据服务器配置合理初始化连接池
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setMaxPoolSize(corePoolSize * 2);
        // 连接池队列容量
        final int queueCapacity = EnvConstant.getInt("spring.async.queueCapacity");
        taskExecutor.setQueueCapacity(queueCapacity);
        // 线程池前缀名称
        final String threadName = EnvConstant.getString("spring.async.threadName");
        taskExecutor.setThreadNamePrefix(threadName);
        // 等待任务都执行完毕，再销毁线程池
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置等待销毁超时时间，如果超过这个时候还没有销毁就强制销毁，以确保应用最后能够被关闭，而不是阻塞住
        taskExecutor.setAwaitTerminationSeconds(60 * 10);
        // 线程池初始化
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncUncaughtExceptionHandlerImpl();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Logger.info(log, () -> "[项目启动]-线程池初始化完成……");
    }

}
